package id.amikom.jogjabankfinder;

import id.amikom.jogjabankfinder.entity.Bank;
import id.amikom.jogjabankfinder.entity.Kurs;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.google.android.gms.maps.model.LatLng;

import android.util.Log;

public class JSONHelper
{

	private final String	TAG_ROUTES		= "routes";
	private final String	TAG_LEGS		= "legs";
	private final String	TAG_STEPS		= "steps";
	private final String	TAG_POLYLINE	= "polyline";
	private final String	TAG_POINTS		= "points";
	private final String	TAG_START		= "start_location";
	private final String	TAG_END			= "end_location";
	private final String	TAG_LAT			= "lat";
	private final String	TAG_LNG			= "lng";
	private final String	TAG_DISTANCE	= "distance";
	private final String	TAG_DURATION	= "duration";
	private final String	TAG_TEXT		= "text";
	private final String	TAG_KODEBANK	= "kodebank";
	private final String	TAG_NAMA		= "nama";
	private final String	TAG_DESC		= "desc";
	private final String	TAG_KURS		= "kurs";
	private final String	TAG_KODE_KURS	= "kode";
	private final String	TAG_NOMINAL		= "nominal";

	InputStream				is				= null;
	JSONObject				jObj			= null;
	String					json			= "";

	public JSONHelper()
	{
		// TODO Auto-generated constructor stub
	}

	/*
	 * Untuk decode Polyline
	 * 
	 * @params String
	 * 
	 * @return ArrayList<LatLng>
	 */
	private ArrayList<LatLng> decodePoly(String encoded)
	{
		ArrayList<LatLng> poly = new ArrayList<LatLng>();
		int index = 0, len = encoded.length();
		int lat = 0, lng = 0;
		while (index < len)
		{
			int b, shift = 0, result = 0;
			do
			{
				b = encoded.charAt(index++) - 63;
				result |= (b & 0x1f) << shift;
				shift += 5;
			} while (b >= 0x20);
			int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
			lat += dlat;
			shift = 0;
			result = 0;
			do
			{
				b = encoded.charAt(index++) - 63;
				result |= (b & 0x1f) << shift;
				shift += 5;
			} while (b >= 0x20);
			int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
			lng += dlng;

			LatLng position = new LatLng((double) lat / 1E5, (double) lng / 1E5);
			poly.add(position);
		}
		return poly;

	}

	public JSONObject getJSONFromUrl(String url)
	{
		// Making HTTP request
		try
		{
			// defaultHttpClient
			DefaultHttpClient httpClient = new DefaultHttpClient();
			HttpGet httpGet = new HttpGet(url);

			HttpResponse httpResponse = httpClient.execute(httpGet);
			HttpEntity httpEntity = httpResponse.getEntity();
			is = httpEntity.getContent();

		} catch (UnsupportedEncodingException e)
		{
			e.printStackTrace();
		} catch (ClientProtocolException e)
		{
			e.printStackTrace();
		} catch (IOException e)
		{
			e.printStackTrace();
		}

		try
		{
			BufferedReader reader = new BufferedReader(new InputStreamReader(
					is, "iso-8859-1"), 8);
			StringBuilder sb = new StringBuilder();
			String line = null;
			while ((line = reader.readLine()) != null)
			{
				sb.append(line + "\n");
			}
			is.close();
			json = sb.toString();
		} catch (Exception e)
		{
			// Log.e("Buffer Error", "Error converting result " + e.toString());
		}

		// try parse the string to a JSON object
		try
		{
			jObj = new JSONObject(json);
		} catch (JSONException e)
		{
			// Log.e("JSON Parser", "Error parsing data " + e.toString());
		}

		// return JSON String
		return jObj;
	}

	/*
	 * Untuk mendapatkan data nilai tukar mata uang
	 * 
	 * @params JSONObject
	 * 
	 * @return Double
	 */
	public Double getCurrentCurrency(JSONObject jObj)
	{
		String TAG_TO = "to";
		String TAG_AMOUNT = "amount";
		Double amount = 0.0;

		try
		{
			JSONObject jObject = jObj.getJSONObject(TAG_TO);
			amount = jObject.getDouble(TAG_AMOUNT);

		} catch (JSONException e)
		{
			// TODO: handle exception
			e.printStackTrace();
			Log.d("errorr json", "gagal dapet : " + e.getMessage());
		}
		return amount;

	}

	/*
	 * Untuk mendapatkan kodebank
	 * 
	 * @params JSONObject
	 * 
	 * @return ArrayList<HashMap<String, String>>
	 */
	public ArrayList<HashMap<String, String>> getKodeBank(JSONObject jsonObject)
	{
		String TAG_KODEBANK = "kodebank";
		String TAG_NAMA = "nama";
		String TAG_KODE = "kode";

		ArrayList<HashMap<String, String>> listKodeBank = new ArrayList<HashMap<String, String>>();

		try
		{
			JSONArray jsArrayKodebank = jsonObject.getJSONArray(TAG_KODEBANK);

			for (int i = 0; i < jsArrayKodebank.length(); i++)
			{
				JSONObject jobjBank = jsArrayKodebank.getJSONObject(i);
				String nama = jobjBank.getString(TAG_NAMA);
				String kode = jobjBank.getString(TAG_KODE);

				HashMap<String, String> map = new HashMap<String, String>();

				Log.d("add kode bank", "nama " + nama + ", kode " + kode);
				map.put(TAG_NAMA, nama);
				map.put(TAG_KODE, kode);
				listKodeBank.add(map);
			}
		} catch (Exception e)
		{
			// TODO: handle exception
		}
		return listKodeBank;
	}

	public ArrayList<Kurs> getAllKurs(JSONObject jsonObject)
	{
		ArrayList<Kurs> listKurs = new ArrayList<Kurs>();

		try
		{
			JSONArray arrayKurs = jsonObject.getJSONArray(TAG_KURS);

			for (int i = 0; i < arrayKurs.length(); i++)
			{
				JSONObject jObject = arrayKurs.getJSONObject(i);
				String kode = jObject.getString(TAG_KODE_KURS);
				Double nominal = jObject.getDouble(TAG_NOMINAL);

				Utils.TRACE("add kurs " + kode + "," + nominal);

				listKurs.add(new Kurs(kode, nominal));
			}
		} catch (JSONException e)
		{
			// TODO: handle exception
			Utils.TRACE(e.toString());
		}

		return listKurs;
	}

	/*
	 * Untuk mendapatkan data lokasi bank
	 * 
	 * @params JSONObject
	 * 
	 * @return ArrayList<Bank>
	 */
	public ArrayList<Bank> getAllBankLocation(JSONObject jsonObject)
	{

		ArrayList<Bank> listBank = new ArrayList<Bank>();

		try
		{
			JSONArray arrayBank = jsonObject.getJSONArray(TAG_KODEBANK);

			for (int i = 0; i < arrayBank.length(); i++)
			{
				JSONObject jObject = arrayBank.getJSONObject(i);

				String name = jObject.getString(TAG_NAMA);
				String desc = jObject.getString(TAG_DESC);
				double lat = jObject.getDouble(TAG_LAT);
				double lng = jObject.getDouble(TAG_LNG);

			//	Log.d("add posisi bank", "lat :" + lat + " lng:" + lng);
				listBank.add(new Bank(name, desc, lat, lng));
			}
		} catch (Exception e)
		{
			// TODO: handle exception
		}

		return listBank;

	}

	/*
	 * Untuk mendapatkan direction
	 * 
	 * @params JSONObject
	 * 
	 * @return ArrayList<LatLng>
	 */
	public ArrayList<LatLng> getDirection(JSONObject jObj)
	{

		ArrayList<LatLng> directions = new ArrayList<LatLng>();

		try
		{
			JSONObject objRoute = jObj.getJSONArray(TAG_ROUTES).getJSONObject(0);
			Utils.TRACE("get Routes");
			JSONObject objLegs = objRoute.getJSONArray(TAG_LEGS).getJSONObject(0);
			Utils.TRACE("get Legs");
			JSONArray arraySteps = objLegs.getJSONArray(TAG_STEPS);
			Utils.TRACE("get Array Steps");
			for (int wi2t = 0; wi2t < arraySteps.length(); wi2t++)
			{
				JSONObject step = arraySteps.getJSONObject(wi2t);
				JSONObject objStart = step.getJSONObject(TAG_START);
				JSONObject objEnd = step.getJSONObject(TAG_END);
				double latStart = objStart.getDouble(TAG_LAT);
				double lngStart = objStart.getDouble(TAG_LNG);

				directions.add(new LatLng(latStart, lngStart));

				JSONObject poly = step.getJSONObject(TAG_POLYLINE);
				String encodedPoly = poly.getString(TAG_POINTS);

				ArrayList<LatLng> decodedPoly = decodePoly(encodedPoly);
				for (int eka = 0; eka < decodedPoly.size(); eka++)
				{
					directions.add(new LatLng(decodedPoly.get(eka).latitude, decodedPoly.get(eka).longitude));
				}

				double latEnd = objEnd.getDouble(TAG_LAT);
				double lngEnd = objEnd.getDouble(TAG_LNG);
				directions.add(new LatLng(latEnd, lngEnd));

			}
		} catch (JSONException e)
		{
			// TODO: handle exception
		}

		return directions;
	}

	public String getDistance(JSONObject jsonObject)
	{
		String distance = null;

		try
		{
			JSONObject objRoute = jObj.getJSONArray(TAG_ROUTES).getJSONObject(0);
			Utils.TRACE("get Routes");
			JSONObject objLegs = objRoute.getJSONArray(TAG_LEGS).getJSONObject(0);
			Utils.TRACE("get Legs");
			JSONObject objDistance = objLegs.getJSONObject(TAG_DISTANCE);

			distance = objDistance.getString(TAG_TEXT);
			Utils.TRACE("distance :" + distance);

		} catch (JSONException e)
		{
			// TODO: handle exception
			Utils.TRACE("JSON distance gagal : " + e.toString());
		}
		return distance;
	}

	public String getDuration(JSONObject jsonObject)
	{
		String duration = null;

		try
		{
			JSONObject objRoute = jObj.getJSONArray(TAG_ROUTES).getJSONObject(0);
			Utils.TRACE("get Routes");
			JSONObject objLegs = objRoute.getJSONArray(TAG_LEGS).getJSONObject(0);
			Utils.TRACE("get Legs");
			JSONObject objDistance = objLegs.getJSONObject(TAG_DURATION);

			duration = objDistance.getString(TAG_TEXT);
			Utils.TRACE("duration :" + duration);
		} catch (JSONException e)
		{
			// TODO: handle exception
			Utils.TRACE("JSON duration gagal : " + e.toString());
		}

		return duration;
	}

}
